/**
 * @addtogroup object.h
 * object.h
 * @{
 */
/**
 * @file ofc_object.h
 * @brief 基础类定义
 * @note
 * @author Leo

 * @par          修改日志
 * <table>
 * <tr><th>Date<th>Version<th>Author<th>Description
 * <tr><td>2018-11-19<td>1.0<td>Leo<td>创建初始版本
 * <tr><td>2019-05-24<td>1.1<td>Leo<td>仅更换文件名称,从hqc_object -> oc_object.h
 * <tr><td>2019-11-13<td>1.2<td>Leo<td>仅更换文件名称,从oc_object -> ofc_object.h
 * <tr><td>2020-02-10<td>1.3<td>Leo<td>增加TOfNotifyEvent
 * <tr><td>2020-07-10<td>1.4<td>Leo<td>增加内存屏障函数,内部实现默认的OfMalloc函数和OfFree函数,并支持用户自定义动态内存分配函数
 * <tr><td>2020-12-29<td>1.5<td>Leo<td>如果已经包含了Kyee的库,则这里的内存屏障去掉
 * <tr><td>2021-07-21<td>1.6<td>Leo<td> elif !defined(__linux)
 * <tr><td>2021-08-04<td>1.7<td>Leo<td>增加arm64内核下下的dmb() dsb()支持
 * <tr><td>2021-10-22<td>1.8<td>Leo<td>在kernel模式下,加入包含atomic.h,解决有些内核(xm8520d)未定义dmb的错误
 * <tr><td>2022-05-09<td>1.9<td>Leo<td>加入像ubuntu-x86这样的系统下没有定义dmb,__ARM_ARCH等宏
 * <tr><td>2024-07-22<td>2.0<td>Akee<td>增加__aarch64__宏判断64位系统(ac8257_64bit)
 * @copyright 杭州鸿泉物联网技术股份有限公司
 */
#ifndef _OFC_OBJECT_H_
#define _OFC_OBJECT_H_

#include "ofc_types.h"

#ifdef __cplusplus
extern "C" {
#endif

/**
* 将类的虚方法指向具体实现的方法,在类中调用
* @param name 虚方法名
* @param method 具体实现的方法
*/
#define ASSIGN_METHOD(name, method) \
    self->name = method;

/**
* 虚方法的覆盖,在子类中调用
* @param ancestor_class: 父类的类名
* @param name 虚方法名
* @param method 具体实现的方法
*/
#define OVERRIDE_METHOD(ancestor_class, name, method)\
    self->name##_ = ((ancestor_class *)self)->name;\
    ((ancestor_class *)self)->name = method;

typedef struct TOfObjectTag TOfObject;
typedef void (*TOfVirtualMethod)(TOfObject *self);

/**
 * TOfNotifyEvent事件
 * @param sender: 调用者对象指针
 * @return 无返回值
 */
typedef void (*TOfNotifyEvent)(TOfObject *sender);

/**
 * TOfDoNotify事件
 * @param sender: 调用者对象指针
 * @return 无返回值
 */
typedef void (*TOfDoNotify)(void *sender);

/**
 * TOfOnNotify事件
 */
typedef struct TOfOnNotifyTag TOfOnNotify;

/**
* @param object: 对象指针,相当于类中的self
* @param Method: 具体的方法
*/
struct TOfOnNotifyTag
{
    void *object;
    TOfDoNotify Method;
};

#define PRIVATE ///<定义私有成员,在类中可起到分隔作用
#define PROTECTED ///<定义受保护成员,在类中可起到分隔作用
#define PUBLIC ///<定义公共成员,在类中可起到分隔作用

typedef void *(*TOfMalloc)(TSize size);
typedef void (*TOfFree)(void *);

/**
 * Ofc内存分配函数
 * @note 
 *  1. 库内部未实现动态内存分配的功能,仅仅返回NULL
 *  2. 如果需要支持动态内存分配的功能,动态内存分配函数需要由用户提供,通过OfSetMallocProc告知系统
 * @param size: 分配内存的大小
 * @return 内存分配成功,返回分配的内存指针,否则返回NULL
 */
void *OfMalloc(TSize size);

/**
 * Ofc内存释放函数
 * @note 
 *  1. 库内部未实现动态内存释放的功能,函数为空函数
 *  2. 如果需要支持动态内存释放的功能,动态内存释放函数需要由用户提供,通过OfSetFreeProc告知系统
 * @param ptr: 释放内存的指针
 * @return 无返回值
 */
void OfFree(void *ptr);

/**
 * 使用用户自定义的动态内存分配函数来代替系统默认的动态内存分配函数
 * @param malloc_proc: 用户自定义的动态内存分配函数
 * @return 返回原先的动态内存分配函数指针
 */
TOfMalloc OfSetMallocProc(TOfMalloc malloc_proc);

/**
 * 使用用户自定义的动态内存释放函数来代替系统默认的动态内存释放函数
 * @param free_proc: 用户自定义的动态内存释放函数
 * @return 返回原先的动态内存释放函数指针
 */
TOfFree OfSetFreeProc(TOfFree free_proc);

#ifndef _KYUtils_H_

// 2022-05-09: 增加,用于像ubuntu-x86这样的系统下在上述的头文件中没有定义__ARM_ARCH,__LINUX_ARM_ARCH__
#ifndef __ARM_ARCH
#define __ARM_ARCH 0
#endif 

#ifndef __LINUX_ARM_ARCH__
#define __LINUX_ARM_ARCH__ 0
#endif 

// 内存屏障, 2020-07-10, 源自Kyee.KYUtils.h
#if defined(_WIN32) || defined(_WIN64) || defined(_WINDOWS) || defined(WINCE)
 
    #define barrier()
 
    #define isb()     barrier()
    #define dsb()     barrier()
    #define dmb()     barrier()

    #define mb()      barrier()
    #define rmb()     barrier()
    #define wmb()     barrier()
 
    #define smp_mb()  barrier()
    #define smp_rmb() barrier()
    #define smp_wmb() barrier()
 
#elif !defined(__linux)

#ifdef __ICCARM__
    #define dsb()     __asm volatile("dsb" ::: "memory")
    #define dmb()     __asm volatile("dmb" ::: "memory")
    #define isb()     __asm volatile("isb" ::: "memory")
    #define barrier() __asm volatile("" ::: "memory")
#elif defined(__CC_ARM) || defined(__ARMCC_VERSION)
    #define barrier() __schedule_barrier()

    #define isb()     __schedule_barrier();\
                      __isb(0xF);\
                      __schedule_barrier();
                      
    #define dsb()     __schedule_barrier();\
                      __dsb(0xF);\
                      __schedule_barrier();
                      
    #define dmb()     __schedule_barrier();\
                      __dmb(0xF);\
                      __schedule_barrier();
 
    #define mb()      barrier()
    #define rmb()     barrier()
    #define wmb()     barrier()
 
    #define smp_mb()  barrier()
    #define smp_rmb() barrier()
    #define smp_wmb() barrier()
#elif __ARM_ARCH >= 8 || __LINUX_ARM_ARCH__ >= 8
    #define isb()     __asm__ __volatile__ ("isb" : : : "memory")
    #define dsb()     __asm__ __volatile__ ("dsb st" : : : "memory")
    #define dmb()     __asm__ __volatile__ ("dmb st" : : : "memory")
#elif __ARM_ARCH == 7 || __LINUX_ARM_ARCH__ == 7
    #define isb()     __asm__ __volatile__ ("isb" : : : "memory")
    #define dsb()     __asm__ __volatile__ ("dsb" : : : "memory")
    #define dmb()     __asm__ __volatile__ ("dmb" : : : "memory")
#elif defined(CONFIG_CPU_XSC3) || __ARM_ARCH == 6 || __LINUX_ARM_ARCH__ == 6
    #define isb()     __asm__ __volatile__ ("mcr p15, 0, %0, c7, c5, 4"  : : "r"(0) : "memory")
    #define dsb()     __asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 4" : : "r"(0) : "memory")
    #define dmb()     __asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 5" : : "r"(0) : "memory")
#else
    #error unknown compile
#endif

#elif defined(__KERNEL__)
    #include <linux/compiler.h>
    #include <linux/bitops.h>
    #include <linux/atomic.h>

#ifndef dmb  // 2022-05-09: 增加,用于像ubuntu-x86这样的系统下在上述的头文件中没有定义dmb
#define isb()     __asm__ __volatile__ ("" : : : "memory")
#define dsb()     __asm__ __volatile__ ("" : : : "memory")
#define dmb()     __asm__ __volatile__ ("" : : : "memory")
#endif 

#else

    #define barrier() __asm__ __volatile__ ("" : : : "memory")

#if defined(__i386__) || defined(__x86_64__)
    #define isb()     __asm__ __volatile__ ("" : : : "memory")
    #define dsb()     __asm__ __volatile__ ("" : : : "memory")
    #define dmb()     __asm__ __volatile__ ("" : : : "memory")
#elif defined(__aarch64__) || __ARM_ARCH >= 8 || __LINUX_ARM_ARCH__ >= 8
    #define isb()     __asm__ __volatile__ ("isb" : : : "memory")
    #define dsb()     __asm__ __volatile__ ("dsb st" : : : "memory")
    #define dmb()     __asm__ __volatile__ ("dmb st" : : : "memory")
#elif __ARM_ARCH == 7 || __LINUX_ARM_ARCH__ == 7
    #define isb()     __asm__ __volatile__ ("isb" : : : "memory")
    #define dsb()     __asm__ __volatile__ ("dsb" : : : "memory")
    #define dmb()     __asm__ __volatile__ ("dmb" : : : "memory")
#elif defined(CONFIG_CPU_XSC3) || __ARM_ARCH == 6 || __LINUX_ARM_ARCH__ == 6
    #define isb()     __asm__ __volatile__ ("mcr p15, 0, %0, c7, c5, 4"  : : "r"(0) : "memory")
    #define dsb()     __asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 4" : : "r"(0) : "memory")
    #define dmb()     __asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 5" : : "r"(0) : "memory")
#elif defined(CONFIG_CPU_FA526)
    #define isb()     __asm__ __volatile__ ("mcr p15, 0, %0, c7, c5, 4"  : : "r"(0) : "memory")
    #define dsb()     __asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 4" : : "r"(0) : "memory")
    #define dmb()     __asm__ __volatile__ ("" : : : "memory")
#else
    #define isb()     __asm__ __volatile__ ("" : : : "memory")
    #define dsb()     __asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 4" : : "r"(0) : "memory")
    #define dmb()     __asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 4" : : "r"(0) : "memory")
    //#define dmb()     __asm__ __volatile__ ("" : : : "memory")
#endif

#ifndef CONFIG_SMP
    #define mb()      barrier()
    #define rmb()     barrier()
    #define wmb()     barrier()
 
    #define smp_mb()  barrier()
    #define smp_rmb() barrier()
    #define smp_wmb() barrier()
#else
    #define mb()      dsb()
    #define rmb()     dmb()
    #define wmb()     mb()
 
    #define smp_mb()  dmb()
    #define smp_rmb() dmb()
    #define smp_wmb() dmb()
#endif

#if defined(CONFIG_CPU_SA1100) || defined(CONFIG_CPU_SA110) \
   || defined(__ARM_ARCH_5E__) || defined(__ARM_ARCH_5TE__)
/*
 * On the StrongARM, "swp" is terminally broken since it bypasses the
 * cache totally.  This means that the cache becomes inconsistent, and,
 * since we use normal loads/stores as well, this is really bad.
 * Typically, this causes oopsen in filp_close, but could have other,
 * more disastrous effects.  There are two work-arounds:
 *  1. Disable interrupts and emulate the atomic swap
 *  2. Clean the cache, perform atomic swap, flush the cache
 *
 * We choose (1) since its the "easiest" to achieve here and is not
 * dependent on the processor type.
 *
 * NOTE that this solution won't work on an SMP system, so explcitly
 * forbid it here.
 */
#define swp_is_buggy
#endif

#endif

#endif // _KYUtils_H_

// 2021-08-04,为了兼容ARM64(dmb有个参数)
#define of_barrier() barrier()
#define of_isb() isb()

#if defined(_DMB_P1_)
#define of_dsb() dsb(st)
#define of_dmb() dmb(st)
#elif defined(_DMB_P0_)
#define of_dsb() dsb()
#define of_dmb() dmb()
#elif __ARM_ARCH >= 8 || __LINUX_ARM_ARCH__ >= 8
#define of_dsb() dsb()
#define of_dmb() dmb()
#else
#define of_dsb() dsb()
#define of_dmb() dmb()
#endif

/**
 * 所有对象的基类
 */
struct TOfObjectTag
{
PUBLIC
    TOfVirtualMethod Destroy;
};

/**
 * TOfObject的构造函数
 * @param self: 对象实例指针
 * @return 无返回值
 * @note 若采用此方法创建对象,需采用[OfDestroyObject](@ref OfDestroyObject)函数销毁对象
 */
void TOfObjectCreate(TOfObject *self);

/**
 * 所有的对象销毁,需要调用该函数.
 * @note 
 * - 该函数只负责销毁对象,而不会释放self的内存.如果需要销毁并释放内存的话用OfFreeObject函数
 * - 如果self不是malloc出来的可以调用这个函数
 * @param self: 对象实例指针
 * @return 无返回值
 */
void OfDestroyObject(TOfObject *self);

/**
 * 创建对象实例的函数.该函数仅仅是分配了对象占用的内存.
 * @param object_size: 对象实例的大小
 * @return 返回创建的对象(注: 该对象未调用任何构造函数)
 * @par 示例
 * @code
 * TOfList * OfCreateList( void )
 * {
 *   TOfList *result = (TOfList *)OfCreateObject(sizeof(*result));
 *  
 *   if (result != NULL)
 *       TOfListCreate(result);
 *
 *   return result;
 * }
 * @endcode
 * @note 若采用此方法创建对象,需采用[OfFreeObject](@ref OfFreeObject)函数释放内存
 */
TOfObject *OfCreateObject(Int32 object_size);

/**
 * - 调用对象的析构函数,并释放self指向的内存.
 * - 仅动态分配出来的对象用这个函数,否则用OfDestroyObject函数
 * @param self: 对象实例指针
 * @return 无返回值
 */
void OfFreeObject(TOfObject *self);

#ifdef __cplusplus
}  // extern "C"
#endif

#endif // _OFC_OBJECT_H_

/**
 * @}
 */
